<?php
/***************************************************************
*  Copyright notice
*
*  (c) 2005 - 2008 Ingo Schmitt <is@marketing-factory.de>
*  All rights reserved
*
*  This script is part of the Typo3 project. The Typo3 project is
*  free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  The GNU General Public License can be found at
*  http://www.gnu.org/copyleft/gpl.html. 
*
*  This script is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
 * Plugin 'checkout' for the 'commerce' extension.
 * This plugin handles everything concerning the checkout. It gets his configuration completely from TypoScript.
 * Every step is a collection of single modules. Each module is represented by a class that provides several methods
 * for displaying forms, checking data and storing data.
 *
 * @package		TYPO3
 * @subpackage	tx_commerce
 * @author		Thomas Hempel	<thomas@work.de>
 * @author		Ingo Schmitt	<is@marketing-factory.de>
 * @author		Volker Graubaum	<vg@e-netconsulting.de>
 * @maintainer		Thomas Hempel	<thomas@work.de>
 *
 * $Id: class.tx_commerce_pi3.php 576 2007-03-22 22:38:22Z ingo $
 */

require_once(PATH_tslib.'class.tslib_pibase.php');
require_once(PATH_t3lib.'class.t3lib_tcemain.php');
/**
 * tx_commerce includes
 */
require_once(PATH_txcommerce.'lib/class.tx_commerce_product.php');
require_once(PATH_txcommerce.'lib/class.tx_commerce_category.php');
require_once(PATH_txgraytree.'lib/class.tx_graytree_folder_db.php');
require_once(PATH_txcommerce.'lib/class.tx_commerce_pibase.php');
require_once(PATH_txcommerce.'lib/class.tx_commerce_div.php');
require_once(PATH_txcommerce.'pi4/class.tx_commerce_pi4.php');
require_once(t3lib_extMgm::extPath('static_info_tables').'pi1/class.tx_staticinfotables_pi1.php');

class tx_commerce_pi3 extends tx_commerce_pibase {
	var $prefixId = 'tx_commerce_pi3';				// Same as class name
	var $scriptRelPath = 'pi3/class.tx_commerce_pi3.php';	// Path to this script relative to the extension dir.
	var $extKey = 'commerce';					// The extension key.
	var $imgFolder = '';

	var $templateCode = '';
	var $dbFieldData = array();
	var $formError = array();
	
	/**
	 * Holding the Static_info Object
	 * 
	 * @var Object
	 */	
	var $staticInfo;

	var $currentStep = '';

	/**
	 * Order ID of the Order
	 * Is generated by HOOK generateOrderId if available, otherwise is generated by uniqid
	 */
	var $orderId;
	var $currency = '';

	/**
	 * If set to TRUE some debug message will be printed.
	 */
	var $debug = false;

	/**
	 * @var 	boolean		true if checkoutmail to user send correctly
	 */
	var $userMailOK;
	/**
	 * @var 	boolean		true if checkoutmail to Admin send correctly
	 */
	var $adminMailOK;
	
	/**
	 * you have to implement a false by your own
	 * @var		boolean		true if finish IT is ok
	 * 
	 */
	var $finishItOK = true;
	
	/**
	 * Array of Checkout Steps
	 *
	 * @var array
	 */
	var $CheckOutsteps = array();

	 /**
	 * Array of the ExtConf
	 *
	 * @var array
	 */
	var $extConf = array();

	 /**
	 * String to clear Session after checkout
	 *
	 * @var array
	 */
	var $clearSessionAfterCheckout = true;
	
	/**
	 * Init Method, autmatically called $this->main
	 * @param 	string	$conf	TypoConfiguration
	 */
	function init($conf){

		parent::init($conf);
		$this->conf = $conf;
		$this->pi_setPiVarDefaults();
		$this->pi_loadLL();
		$this->conf['basketPid']=$GLOBALS['TSFE']->id;
		$this->staticInfo = t3lib_div::makeInstance('tx_staticinfotables_pi1');
	    $this->staticInfo->init();
		
	    $this->extConf = unserialize($GLOBALS["TYPO3_CONF_VARS"]["EXT"]["extConf"]["commerce"]);
		
		$this->imgFolder = 'uploads/tx_commerce/';

		if ($this->conf['currency']>'')	{
			$this->currency = $this->conf['currency'];
		}
		if (empty($this->currency))	{
			$this->currency = 'EUR';
		}
		$this->CheckOutsteps[0] = 'billing';
		$this->CheckOutsteps[1] = 'delivery';
		$this->CheckOutsteps[2] = 'payment'; 
		$this->CheckOutsteps[3] = 'listing';
		$this->CheckOutsteps[4] = 'finish';
		/**
         * Hook for handling own steps and information   
         * @since 27.04.2006
         *
		 */

         $hookObjectsArr = array();
                
         if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['init'])){
             foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['init'] as $classRef)   {
                 $hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
             }
         }
                
         foreach($hookObjectsArr as $hookObj)    {
              if (method_exists($hookObj, 'CheckoutSteps'))     {
                                $hookObj->CheckoutSteps($this->CheckOutsteps,$this);
             }
        } 
	}

	/**
	 *
	 * Main Method, automatically called by TYPO3 wher inserting the plugin
	 * @param 	string	$content from Parent Page
	 * @param 	array	$conf	TS-Configuration
	 * @return	string	HTML-Content
	 */
	function main($content, $conf)	{
		global $TYPO3_CONF_VARS;
		$this->init($conf);
		#$GLOBALS['TSFE']->set_no_cache();
		
		if ($this->debug) debug($this->piVars, 'piVars' , __FILE__ , __LINE__);
		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['main']))	{
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['main'] as $classRef)	{
				$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}
	
		
		/**
		 * Set basket to readonly, if set in Extension Configuration
		 * 
		 */
		if ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce']['lockBasket'] == 1) {
			$GLOBALS['TSFE']->fe_user->tx_commerce_basket->setReadOnly();
			$GLOBALS['TSFE']->fe_user->tx_commerce_basket->store_data();
		
		}
		if ($this->debug) debug($GLOBALS['TSFE']->fe_user->tx_commerce_basket, 'commerce_basket', __FILE__ , __LINE__);
			// store the current step
		$this->currentStep = strtolower($this->piVars['step'] );
		
		
		
		
			// set deliverytyp as current step, if the user comes from pi4 and created a new address
		if (empty($this->currentStep) && $this->piVars['addressType']) {
			switch($this->piVars['addressType']) {
				case '2': 
					$this->currentStep = 'delivery';
				break;
				default:
			}
		}
		
                /**
                 * Hook for handling own steps and information   
                 * @since 27.04.2006
                 *
                 */

                $hookObjectsArr = array();
                
                if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['main'])){
                        foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['main']
                        as $classRef)   {
                                $hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
                        }
                }
                
                foreach($hookObjectsArr as $hookObj)    {
                        if (method_exists($hookObj, 'processData'))     {
                                $hookObj->processData($this);
                        }
                } 		
		
			// write the billing address into session, if it is present in the REQUEST
		if (isset($this->piVars['billing']))	$GLOBALS['TSFE']->fe_user->setKey('ses', tx_commerce_div::generateSessionKey('billing'), $this->piVars['billing']);
		if (isset($this->piVars['delivery']))	$GLOBALS['TSFE']->fe_user->setKey('ses', tx_commerce_div::generateSessionKey('delivery'), $this->piVars['delivery']);
		if (isset($this->piVars['payment'])) 	$GLOBALS['TSFE']->fe_user->setKey('ses', tx_commerce_div::generateSessionKey('payment'), $this->piVars['payment']);

			// fetch the address data from hidden fields if the address_id is set what means that
			// the address was selected from list with radio buttons.
		if (isset($this->piVars['address_uid']))	{
				//override missing or incorrect email with username if username is email, because we need to be sure to have at least one correct mail address
				//this way email is not necessarily mandatory for billing/delivery address
			if (!$this->conf['randomUser'] && !t3lib_div::validEmail($this->piVars[$this->piVars['address_uid']]['email'])) $this->piVars[$this->piVars['address_uid']]['email'] = $GLOBALS["TSFE"]->fe_user->user['email'];
			$this->piVars[$this->piVars['address_uid']]['uid'] = $this->piVars['address_uid'];
			$GLOBALS['TSFE']->fe_user->setKey('ses', tx_commerce_div::generateSessionKey($this->piVars['check']), $this->piVars[$this->piVars['address_uid']]);
		}
	
		$this->MYSESSION['billing'] = $GLOBALS['TSFE']->fe_user->getKey('ses', tx_commerce_div::generateSessionKey('billing'));
		$this->MYSESSION['delivery'] = $GLOBALS['TSFE']->fe_user->getKey('ses', tx_commerce_div::generateSessionKey('delivery'));
		$this->MYSESSION['payment'] = $GLOBALS['TSFE']->fe_user->getKey('ses', tx_commerce_div::generateSessionKey('payment'));
		$this->MYSESSION['mails'] = $GLOBALS['TSFE']->fe_user->getKey('ses', tx_commerce_div::generateSessionKey('mails'));
		
		if(($this->piVars['check'] == 'billing') && ($this->piVars['step'] == 'payment')){
			// remove reference to delivery address
			$this->MYSESSION['delivery'] = false;
			$GLOBALS['TSFE']->fe_user->setKey('ses', tx_commerce_div::generateSessionKey('delivery'),false);
		}
		/**
		* Return if checkout is not allowed. Currently the method always returns TRUE right now.
		* Some functionality has to be implemented in future.
		*/
		
		$canMakeCheckout = $this->canMakeCheckout();
		if (is_string($canMakeCheckout))	{
			return $this->cObj->cObjGetSingle($this->conf['cantMakeCheckout.'][$canMakeCheckout], $this->conf['cantMakeCheckout.'][$canMakeCheckout.'.']);
		}
			// get the template
		$this->templateCode = $this->cObj->fileResource($this->conf['templateFile']);

			// define the currency
		if ($this->conf['currency']>'')	{
			$this->currency = $this->conf['currency'];
		}
		if ($this->debug) debug($this->currentStep);
		// debug($GLOBALS['TSFE']->fe_user->tx_commerce_basket);
		
		
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'preSwitch'))	{
				 $hookObj->preSwitch($this->currentStep, $this);
			}
		}
		
		
		switch ($this->currentStep)	{
			case 'delivery':
					// get delivery address
				$content = $this->getDeliveryAddress();
				break;
			case 'payment':
				$paymentObj = $this->getPaymentObject();
				$content = $this->handlePayment($paymentObj);
				// only break at this point if we need some payment handling otherwise go on to the next step
				if ($content != false) break;
				// go on with listing
				$this->currentStep = 'listing';
			case 'listing':
				$content = $this->getListing();
				break;
			case 'finish':
				$paymentObj = $this->getPaymentObject();
				$content = $this->finishIt($paymentObj);
				break;
			case 'billing':
				 $content = $this->getBillingAddress();
				  break;
			default:
                 foreach($hookObjectsArr as $hookObj)    {
                    if (method_exists($hookObj, $this->currentStep))        {
                        $method = $this->currentStep;
                        $content = $hookObj->$method($this);
                    }
                 }
                 if(!$content){
                       // get billing address
                       $content = $this->getBillingAddress();
                  }
                  break;

		}
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'postSwitch'))	{
				$content = $hookObj->postSwitch($this->currentStep, $content, $this);
			}
		}
		$GLOBALS['TSFE']->fe_user->setKey('ses', tx_commerce_div::generateSessionKey('currentStep'), $this->currentStep);
		
		$content = $this->renderSteps($content);
		
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'postRender'))	{
				$content = $hookObj->postRender($this->currentStep, $content, $this);
			}
		}
		return $this->pi_WrapInBaseClass($content);
	}
	/**
	 * This method renders the step layout into the checkout process
	 * It replaces the subpart ###CHECKOUT_STEPS### 
	 *
	 * @param string $content
	 * @return string $content
	 * @author	Ingo Schmitt <is@marketing-factory.de>
	 */
	
	function renderSteps($content) {
		
		$myTemplate = $this->cObj->getSubpart($this->templateCode,'###CHECKOUT_STEPS_BAR###');
		$activeTemplate = $this->cObj->getSubpart($myTemplate,'###CHECKOUT_ONE_STEP_ACTIVE###');
		$actualTemplate = $this->cObj->getSubpart($myTemplate,'###CHECKOUT_ONE_STEP_ACTUAL###');
		$inactiveTemplate = $this->cObj->getSubpart($myTemplate,'###CHECKOUT_ONE_STEP_INACTIVE###');
		$stepsToNumbers=array_flip($this->CheckOutsteps);
	
		$currentStepNumber=$stepsToNumbers[$this->currentStep];
		
		$activeContent = '';
		$inactiveContent = '';
		for ($i=0;$i<$currentStepNumber;$i++){
			$localTs=$this->conf['activeStep.'];
			if ($localTs['typolink.']['setCommerceValues']=1) {
				$localTs['typolink.']['parameter']=$this->conf['basketPid'];
				$localTs['typolink.']['additionalParams'] = ini_get('arg_separator.output').$this->prefixId.'[step]='.$this->CheckOutsteps[$i];
	
			}
			
			$label = sprintf($this->pi_getLL('label_step_'.$this->CheckOutsteps[$i]), $i + 1);
			$lokContent = $this->cObj->stdWrap($label, $localTs);
			
			$activeContent.=$this->cObj->substituteMarker($activeTemplate,'###LINKTOSTEP###',$lokContent);
		}
		$label = sprintf($this->pi_getLL('label_step_'.$this->CheckOutsteps[$i]), $i + 1);
		$lokContent = $this->cObj->stdWrap($label, $this->conf['actualStep.']);
 		$actualContent = $this->cObj->substituteMarker($actualTemplate,'###STEPNAME###',$lokContent);
		for ($i=($currentStepNumber+1);$i < count($this->CheckOutsteps);$i++){
			
			$label = sprintf($this->pi_getLL('label_step_'.$this->CheckOutsteps[$i]), $i + 1);
			$lokContent = $this->cObj->stdWrap($label, $this->conf['inactiveStep.']);
 			
			$inactiveContent.=$this->cObj->substituteMarker($inactiveTemplate,'###STEPNAME###',$lokContent);
			
		}
		$myTemplate=$this->cObj->substituteSubpart($myTemplate,'###CHECKOUT_ONE_STEP_ACTIVE###',$activeContent);
		$myTemplate=$this->cObj->substituteSubpart($myTemplate,'###CHECKOUT_ONE_STEP_INACTIVE###',$inactiveContent);
		$myTemplate=$this->cObj->substituteSubpart($myTemplate,'###CHECKOUT_ONE_STEP_ACTUAL###',$actualContent);
		
		
		$content = $this->cObj->substituteMarker($content,'###CHECKOUT_STEPS###',$myTemplate);
		
		return $content;
	}
	/** STEP ROUTINES **/

	/**
	 * Creates a form for collection the billing address data.
	 */
	function getBillingAddress($withTitle = 1)	{
		
		if ($this->conf['billing.']['subpartMarker.']['containerWrap']) {
			$template = $this->cObj->getSubpart($this->templateCode, strtoupper($this->conf['billing.']['subpartMarker.']['containerWrap']));
		} else {
			$template = $this->cObj->getSubpart($this->templateCode, '###ADDRESS_CONTAINER###');
		}

		$markerArray['###ADDRESS_TITLE###'] = '';
		$markerArray['###ADDRESS_DESCRIPTION###'] = '';		

		if ($withTitle == 1)	{
				// fill some standard markers
			$markerArray['###ADDRESS_TITLE###'] = $this->pi_getLL('billing_title');
			$markerArray['###ADDRESS_DESCRIPTION###'] = $this->pi_getLL('billing_description');
		}


		
			// get the form
		$markerArray['###ADDRESS_FORM_TAG###'] = '<form name="addressForm" action="'.$this->pi_getPageLink($GLOBALS['TSFE']->id).'" method="post" '.$this->conf[$this->step.'.']['formParams'].'>';
		$markerArray['###ADDRESS_FORM_HIDDENFIELDS###'] = '<input type="hidden" name="'.$this->prefixId.'[check]" value="billing" />';
		
		$billingForm = '<form name="addressForm" action="'.$this->pi_getPageLink($GLOBALS['TSFE']->id).'" method="post">';
		$billingForm .= '<input type="hidden" name="' .$this->prefixId.'[check]" value="billing" />';
		$markerArray['###HIDDEN_STEP###'] = '<input type="hidden" name="'.$this->prefixId.'[check]" value="billing" />';
	
			// if a user is logged in, get the form from the address management
		if ($GLOBALS['TSFE']->loginUser) {
				// make an instance of pi4 (address management)
			$addressMgm = t3lib_div::makeInstance('tx_commerce_pi4');
			$addressMgm->cObj = $this->cObj;
			$addressMgm->templateCode = $this->templateCode;

			$amConf = $this->conf;
			$amConf['formFields.'] = $this->conf['billing.']['sourceFields.'];
			$amConf['addressPid'] = $this->conf['addressPid'];
			$addressMgm->init($amConf, false);
			$addressMgm->addresses = $addressMgm->getAddresses($GLOBALS['TSFE']->fe_user->user['uid'], $this->conf['billing.']['addressType']);
			$addressMgm->piVars['backpid'] = $GLOBALS['TSFE']->id;
			$markerArray['###ADDRESS_FORM_INPUTFIELDS###']  = $addressMgm->getListing($this->conf['billing.']['addressType'], true, $this->prefixId);
			$billingForm .= $markerArray['###ADDRESS_FORM_INPUTFIELDS###'] ;
		} else {
			$markerArray['###ADDRESS_FORM_INPUTFIELDS###'] = $this->getInputForm($this->conf['billing.'], 'billing');
			$billingForm .= $markerArray['###ADDRESS_FORM_INPUTFIELDS###'] ;
		}

		/**
		 * Build pre selcted Radio Boxes
		 */
		if ($this->piVars['step']=='payment')	{
			$deliveryChecked = '  ';
			$paymentChecked = ' checked="checked" ';
		} elseif ($this->piVars['step'] == 'delivery')	{
			$deliveryChecked = ' checked="checked" ';
			$paymentChecked = '  ';
		} elseif (($this->conf['paymentIsDeliveryAdressDefault'] == 1) )	{
			$deliveryChecked = '  ';
			$paymentChecked = ' checked="checked" ';
		} elseif (($this->conf['deliveryAdressIsSeparateDefault'] == 1))	{
			$deliveryChecked = ' checked="checked" ';
			$paymentChecked = '  ';
		} else {
			$deliveryChecked = '  ';
			$paymentChecked = '  ';
		}

		if ($this->debug) debug($this->MYSESSION, 'MYSESSION', __LINE__, __FILE__ );
		if (is_array($this->MYSESSION['delivery']) && (count($this->MYSESSION['delivery']) > 0))  {
			$deliveryChecked = ' checked="checked" ';
			$paymentChecked = '  ';
		}
		
		
		// for marker for the delivery address chooser
		
		$markerArray['###ADDRESS_RADIOFORM_DELIVERY###'] = '<input type="radio" id="delivery" name="'.$this->prefixId.'[step]" value="delivery" '.$deliveryChecked.'/>';
		$markerArray['###ADDRESS_RADIOFORM_NODELIVERY###']= '<input type="radio" id="nodelivery"  name="'.$this->prefixId.'[step]" value="payment" '.$paymentChecked.'/>';
		$markerArray['###ADDRESS_LABEL_DELIVERY###'] = $this->pi_getLL('billing_deliveryaddress');
		$markerArray['###ADDRESS_LABEL_NODELIVERY###']= $this->pi_getLL('billing_nodeliveryaddress');
		
		// for stdWrap for the delivery address chooser marker
		
		$markerArray['###ADDRESS_RADIOFORM_DELIVERY###']  = $this->cObj->stdWrap($markerArray['###ADDRESS_RADIOFORM_DELIVERY###'] ,$this->conf['billing.']['deliveryAddress.']['delivery_radio.']);
		$markerArray['###ADDRESS_RADIOFORM_NODELIVERY###']  = $this->cObj->stdWrap($markerArray['###ADDRESS_RADIOFORM_NODELIVERY###'] ,$this->conf['billing.']['deliveryAddress.']['nodelivery_radio.']);
		$markerArray['###ADDRESS_LABEL_DELIVERY###']  = $this->cObj->stdWrap($markerArray['###ADDRESS_LABEL_DELIVERY###'] ,$this->conf['billing.']['deliveryAddress.']['delivery_label.']);
		$markerArray['###ADDRESS_LABEL_NODELIVERY###']  = $this->cObj->stdWrap($markerArray['###ADDRESS_LABEL_NODELIVERY###'] ,$this->conf['billing.']['deliveryAddress.']['nodelivery_label.']);
		

		//we are thrown back because address data is not valid
		if (($this->currentStep == 'payment' || $this->currentStep == 'delivery') && !$this->validateAddress('billing')) {
			$markerArray['###ADDRESS_MANDATORY_MESSAGE###'] = $this->pi_getLL('label_loginUser_mandatory_message','data incorrect');
		} else {
			$markerArray['###ADDRESS_MANDATORY_MESSAGE###'] = '';
		}
		
		$markerArray['###ADDRESS_FORM_SUBMIT###'] = '<input type="submit" value="'.$this->pi_getLL('billing_submit').'" />';
		$markerArray['###ADDRESS_DISCLAIMER###'] = $this->pi_getLL('general_disclaimer');

		// @deprecated Marker, use marker above instead (see example Template)
		$markerArray['###ADDRESS_FORM_FIELDS###'] = $billingForm;
		$markerArray['###ADDRESS_RADIO_DELIVERY###'] = '<input type="radio" id="delivery" name="'.$this->prefixId.'[step]" value="delivery" '.$deliveryChecked.'/>'.$this->pi_getLL('billing_deliveryaddress');
		$markerArray['###ADDRESS_RADIO_NODELIVERY###']= '<input type="radio" id="payment"  name="'.$this->prefixId.'[step]" value="payment" '.$paymentChecked.'/>'.$this->pi_getLL('billing_nodeliveryaddress');
		$markerArray=$this->addFormMarker($markerArray,'###|###');
		/**
		 * Hook for processing Marker Array
		 * Inspired by tt_news
		 * @since 21.01.2006
		 *
		 */
		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['getBillingAddress']))	{
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['getBillingAddress'] as $classRef)	{
				$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'ProcessMarker'))	{
				$markerArray = $hookObj->ProcessMarker($markerArray, $this);
			}
		}
		$this->currentStep='billing';
		return $this->cObj->substituteMarkerArray($this->cObj->substituteMarkerArray($template, $markerArray), $this->languageMarker);
	}

	/**
	 * Creates a form for collection the delivery address data.
	 */
	function getDeliveryAddress() {
		if (!$this->validateAddress('billing')){ return $this->getBillingAddress(); }
		$this->validateAddress('delivery');

		if ($this->conf['delivery.']['subpartMarker.']['containerWrap']) {
			$template = $this->cObj->getSubpart($this->templateCode, strtoupper($this->conf['delivery.']['subpartMarker.']['containerWrap']));
		} else {
			$template = $this->cObj->getSubpart($this->templateCode, '###ADDRESS_CONTAINER###');
		}
		
		if ($this->debug) debug($this->MYSESSION, 'MYSESSION', __LINE__, __FILE__ );
			// fill some standard markers
		$markerArray['###ADDRESS_TITLE###'] = $this->pi_getLL('delivery_title');
		$markerArray['###ADDRESS_DESCRIPTION###'] = $this->pi_getLL('delivery_description');

			// get the form
		// Marker Depricated
		$markerArray['###ADDRESS_FORM_TAG###'] = '<form name="addressForm" action="'.$this->pi_getPageLink($GLOBALS['TSFE']->id).'" method="post" '.$this->conf[$this->step.'.']['formParams'].'>';
		
		$markerArray['###ADDRESS_FORM_HIDDENFIELDS###'] = '<input type="hidden" name="'.$this->prefixId.'[step]" value="payment" />'.
								  '<input type="hidden" name="'.$this->prefixId.'[check]" value="delivery" />';
		
		$deliveryForm = '<form name="addressForm" action="'.$this->pi_getPageLink($GLOBALS['TSFE']->id).'" method="post">';
		$deliveryForm .= '<input type="hidden" name="'.$this->prefixId.'[step]" value="payment" />';
		$deliveryForm .= '<input type="hidden" name="'.$this->prefixId.'[check]" value="delivery" />';
		$markerArray['###HIDDEN_STEP###'] = '<input type="hidden" name="'.$this->prefixId.'[step]" value="payment" />';
		$markerArray['###HIDDEN_STEP###'].= '<input type="hidden" name="'.$this->prefixId.'[check]" value="delivery" />';
		// if a user is logged in, get the form from the address management
		if ($GLOBALS['TSFE']->loginUser) {
				// make an instance of pi4 (address management)
			$addressMgm = t3lib_div::makeInstance('tx_commerce_pi4');
			$addressMgm->cObj = $this->cObj;
			$addressMgm->templateCode = $this->templateCode;

			$amConf = $this->conf;
			$amConf['formFields.'] = $this->conf['delivery.']['sourceFields.'];
			$amConf['addressPid'] = $this->conf['addressPid'];

			$addressMgm->init($amConf, false);
			$addressMgm->addresses = $addressMgm->getAddresses($GLOBALS['TSFE']->fe_user->user['uid'], $this->conf['delivery.']['addressType']);

			$addressMgm->piVars['backpid'] = $GLOBALS['TSFE']->id;
			$markerArray['###ADDRESS_FORM_INPUTFIELDS###'] = $addressMgm->getListing($this->conf['delivery.']['addressType'], true, $this->prefixId,$this->MYSESSION['delivery']['uid']);
			if ($this->debug) debug (	$markerArray['###ADDRESS_FORM_INPUTFIELDS###'], 'result of getListing', __LINE__, __FILE__ );
			$deliveryForm .= $markerArray['###ADDRESS_FORM_INPUTFIELDS###'] ;
		} else {
			$markerArray['###ADDRESS_FORM_INPUTFIELDS###'] = $this->getInputForm($this->conf['delivery.'], 'delivery');
			$deliveryForm .= $markerArray['###ADDRESS_FORM_INPUTFIELDS###'] ;
		}
	
		$markerArray['###ADDRESS_RADIOFORM_DELIVERY###'] = '';
		$markerArray['###ADDRESS_RADIOFORM_NODELIVERY###']= '';
		$markerArray['###ADDRESS_LABEL_DELIVERY###'] = '';
		$markerArray['###ADDRESS_LABEL_NODELIVERY###']= '';

		// Marker Depricated, use new Tepmplate
		$markerArray['###ADDRESS_FORM_FIELDS###'] = $deliveryForm;
		$markerArray['###ADDRESS_FORM_SUBMIT###'] = '<input type="submit" value="' .$this->pi_getLL('delivery_submit') .'" />';
		
		//we are thrown back because address data is not valid
		if ($this->currentStep == 'payment' && !$this->validateAddress('delivery')) {
			$markerArray['###ADDRESS_MANDATORY_MESSAGE###'] = $this->pi_getLL('label_loginUser_mandatory_message','data incorrect');
		} else {
			$markerArray['###ADDRESS_MANDATORY_MESSAGE###'] = '';
		}
		$markerArray['###ADDRESS_DISCLAIMER###'] = $this->pi_getLL('general_disclaimer');

		// @deprecated Marker, use ###ADDRESS_FORM_INPUTFIELDS### and ###ADDRESS_FORM_TAG### instead
		$markerArray['###ADDRESS_FORM_FIELDS###'] = $deliveryForm;
		$markerArray['###ADDRESS_RADIO_DELIVERY###'] = '';
		$markerArray['###ADDRESS_RADIO_NODELIVERY###'] = '';
	
		$markerArray=$this->addFormMarker($markerArray,'###|###');
		/**
		 * Hook for processing Marker Array
		 * Inspired by tt_news
		 * @since 21.01.2006
		 */
		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['getDeliveryAddress']))	{
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['getDeliveryAddress'] as $classRef)	{
				$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'ProcessMarker'))	{
				$markerArray=$hookObj->ProcessMarker($markerArray,$this);
			}
		}
		$this->currentStep='delivery';
		return $this->cObj->substituteMarkerArray($this->cObj->substituteMarkerArray($template, $markerArray), $this->languageMarker);
	}

	/**
	 * This method handles all the stuff concerning the payment.
	 *
	 * @param	object	$paymentObj: The payment object
	 * @return	Substituted template
	 */
	function handlePayment($paymentObj = NULL)	{
		if (!$this->validateAddress('delivery')) return $this->getDeliveryAddress();
		if (!$this->validateAddress('billing')) return $this->getBillingAddress();

		
		$sysConfig = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extKey]['SYSPRODUCTS']['PAYMENT'];
		
		$paymentType = $this->getPaymentType();
	
		
		if ($this->conf[$paymentType.'.']['subpartMarker.']['listWrap']) {
			$template = $this->cObj->getSubpart($this->templateCode, strtoupper($this->conf[$paymentType.'.']['subpartMarker.']['listWrap']));
		} else {
			$template = $this->cObj->getSubpart($this->templateCode, '###PAYMENT###');
		}
		

			// fill some standard markers
		$markerArray['###PAYMENT_TITLE###'] = $this->pi_getLL('payment_title');
		$markerArray['###PAYMENT_DESCRIPTION###'] = $this->pi_getLL('payment_description');
		$markerArray['###PAYMENT_DISCLAIMER###'] = $this->pi_getLL('general_disclaimer') .'<br />' .$this->pi_getLL('payment_disclaimer');;

		$config = $sysConfig['types'][strtolower((string)$paymentType)];

			// let's check if we have already a payment object
			// if w edon't have one, let's try to create a new one from the config
		if (!isset($paymentObj))	 {
			
			$errorStr = NULL;
			if (!isset($config['class']))	{
				$errorStr[] = 'class not set!';
			}
			
			if (!file_exists($config['path']))	{
				$errorStr[] = 'file not found!';
			}
			
			if (is_array($errorStr))	die ('PAYMENT:FATAL! No payment possible because I don\'t know how to handle it! ('.implode(', ', $errorStr).')');
			
			$path = $GLOBALS['TSFE']->tmpl->getFileName($config['path']);
			
			require_once($path);
			$paymentObj = t3lib_div::makeInstance($config['class']);
		}
		
		if (
			$paymentObj->needAdditionalData($this) && (
				(isset($this->MYSESSION['payment']) && !$paymentObj->proofData($this->MYSESSION['payment'], $this)) ||
				(!isset($this->MYSESSION['payment']) || $paymentObj->getLastError(1, $this))
				)
			)	{
			
				// merge local lang array
			if (is_array($this->LOCAL_LANG) && isset($paymentObj->LOCAL_LANG))	{
				foreach ($this->LOCAL_LANG as $llKey => $llData)	{
					$newLLData = array_merge($llData, $paymentObj->LOCAL_LANG[$llKey]);
					$this->LOCAL_LANG[$llKey] = $newLLData;
				}
			}
		
			$this->formError = $paymentObj->formError;
			// show the payment form if it's needed, otherwise go to next step
			$paymentForm = '<form name="paymentForm" action="'.$this->pi_getPageLink($GLOBALS['TSFE']->id).'" method="post">';
			$paymentForm .= '<input type="hidden" name="'.$this->prefixId.'[step]" value="payment" />';

			$paymentConfig = $this->conf['payment.'];
			$paymentConfig['sourceFields.'] = $paymentObj->getAdditonalFieldsConfig($this);
			$paymentForm .= $this->getInputForm($paymentConfig, 'payment', true);
			$paymentErr = $paymentObj->getLastError(1,$this);
			$markerArray['###PAYMENT_PAYMENTOBJ_MESSAGE###'] = $this->pi_getLL($paymentErr);
			if($markerArray['###PAYMENT_PAYMENTOBJ_MESSAGE###'] == '' AND $paymentErr != '') {
				$markerArray['###PAYMENT_PAYMENTOBJ_MESSAGE###'] = $this->pi_getLL('defaultPaymentDataError');
			}
			$markerArray['###PAYMENT_FORM_FIELDS###'] = $paymentForm;
			$markerArray['###PAYMENT_FORM_SUBMIT###'] = '<input type="submit" value="' .$this->pi_getLL('payment_submit') .'" /></form>';
			
		} else {
			// redirect to the next page because no additonal payment information is needed or if everything is correct
			return false;
		}

		/**
		 * Hook for processing Marker Array
		 * Inspired by tt_news
		 * @since 21.01.2006
		 *
		 */
		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['handlePayment']))	{
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['handlePayment'] as $classRef)	{
				$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'ProcessMarker'))	{
				$markerArray=$hookObj->ProcessMarker($markerArray,$this);
			}
		}
		$this->currentStep='payment';
		return $this->cObj->substituteMarkerArray($this->cObj->substituteMarkerArray($template, $markerArray),$this->languageMarker);
	}

	/**
	 * Method to list the content of the basket including all articles, sums and addresses.
	 * @param Template for rendering
	 */
	function getListing($template = false)	{

		if (!$template)	{
			$template = $this->cObj->getSubpart($this->templateCode, '###LISTING###');
		}

		if ($this->debug)	debug($GLOBALS['TSFE']->fe_user->tx_commerce_basket);

		$listingForm = '<form name="listingForm" action="'.$this->pi_getPageLink($GLOBALS['TSFE']->id).'" method="post">';
		$listingForm .= '<input type="hidden" name="'.$this->prefixId.'[step]" value="finish" />';
		$markerArray['###HIDDEN_STEP###'] = '<input type="hidden" name="'.$this->prefixId.'[step]" value="finish" />';
		$markerArray['###LISTING_TITLE###'] = $this->pi_getLL('listing_title');
		$markerArray['###LISTING_DESCRIPTION###'] = $this->pi_getLL('listing_description');
		$markerArray['###LISTING_FORM_FIELDS###'] = $listingForm;

		$markerArray['###LISTING_BASKET###'] = $this->makeBasketView(
			$GLOBALS['TSFE']->fe_user->tx_commerce_basket,
			'###BASKET_VIEW###',
			t3lib_div::intExplode(',', $this->conf['regularArticleTypes']),
			array('###LISTING_ARTICLE###','###LISTING_ARTICLE2###')
		);

		$markerArray['###BILLING_ADDRESS###'] = $this->cObj->stdWrap($this->getAddress('billing'),$this->conf['listing.']['stdWrap_billing_address.']);
		$markerArray['###DELIVERY_ADDRESS###'] = $this->cObj->stdWrap($this->getAddress('delivery'),$this->conf['listing.']['stdWrap_delivery_address.']);
		$markerArray['###LISTING_FORM_SUBMIT###'] = '<input type="submit" value="' .$this->pi_getLL('listing_submit') .'" />';
		$markerArray['###LISTING_DISCLAIMER###'] = $this->pi_getLL('listing_disclaimer');
		if ($this->formError['terms'])	{
			$markerArray['###ERROR_TERMS_ACCEPT###'] = $this->cObj->dataWrap($this->formError['terms'],$this->conf['terms.']['errorWrap']);
		} else {
			$markerArray['###ERROR_TERMS_ACCEPT###'] = '';
		}

		if ($this->conf['terms.']['checkedDefault'])	{
			$termsChecked = 'checked';
		}

		/**
		 * @TODO TS Coding with Sacha
		 */
		$comment = isset($this->piVars['comment']) ? $this->piVars['comment'] : '';
		// obsolete, user Label and Form field
		$markerArray['###LISTING_TERMS_ACCEPT###'] = $this->pi_getLL('termstext').'<input type="checkbox" name="'.$this->prefixId.'[terms]" value="termschecked" '.$termsChecked.' />';
		$markerArray['###LISTING_COMMENT###'] = $this->pi_getLL('comment').'<br/><textarea name="'.$this->prefixId.'[comment]" rows="4" cols="40">'.$comment.'</textarea>';
		// Use new version with label and field
		$markerArray['###LISTING_TERMS_ACCEPT_LABEL###'] = $this->pi_getLL('termstext');
		$markerArray['###LISTING_COMMENT_LABEL###'] = $this->pi_getLL('comment');
		$markerArray['###LISTING_TERMS_ACCEPT_FIELD###'] = '<input type="checkbox" name="'.$this->prefixId.'[terms]" value="termschecked" '.$termsChecked.' />';
		$markerArray['###LISTING_COMMENT_FIELD###'] = '<textarea name="'.$this->prefixId.'[comment]" rows="4" cols="40">'.$comment.'</textarea>';

		/**
		 * Hook for processing Marker Array
		 * Inspired by tt_news
		 * @since 21.01.2006
		 *
		 */
		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['getListing']))	{
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['getListing'] as $classRef)	{
				$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'ProcessMarker'))	{
				$markerArray=$hookObj->ProcessMarker($markerArray,$this);
			}
		}
		
	   $markerArray = $this->addFormMarker($markerArray,'###|###');
	   $this->currentStep='listing';
		return $this->cObj->substituteMarkerArray($this->cObj->substituteMarkerArray($template, $markerArray),$this->languageMarker);
	}

	/**
	 * Finishing Page from Checkout
	 * @return	string	HTML-Content
	 */

	function finishIt($paymentObj = NULL)	{
		
		$sysConfig = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extKey]['SYSPRODUCTS']['PAYMENT'];
		$paymentType = $this->getPaymentType();
		$config = $sysConfig['types'][strtolower((string)$paymentType)];

		if (!isset($paymentObj))	{
			if (!isset($config['class']) || !file_exists($config['path'])) die ('FINISHING: FATAL! No payment possible because I don\'t know how to handle it!');
			require_once($config['path']);
			$paymentObj = t3lib_div::makeInstance($config['class']);
		}

		if (method_exists($paymentObj, 'checkExternalData')) {
			$paymentDone = $paymentObj->checkExternalData($_REQUEST, $this->MYSESSION,$this);
		} else {
			$paymentDone = false;
		}
		
		// check if Terms are acceptes
		if (!$paymentDone && (empty($this->piVars['terms']) || ($this->piVars['terms'] != 'termschecked')))	{
			$this->formError['terms']=$this->pi_getLL('error_terms_not_accepted');
			$content = $this->handlePayment($paymentObj);

			if ($content == false)	{
				$this->formError['terms'] = $this->pi_getLL('error_terms_not_accepted');
				$content = $this->getListing();
			}
			return $content;
		}
		
		// check Stockamount of articles
		if(!$this->checkStock()) {
			$content = '<div class="cmrc_mb_no_stock">';
			$content .= $this->pi_getLL('not_all_articles_in_stock');
			$content .= $this->pi_linkToPage($this->pi_getLL('no_stock_back'),$this->conf['noStockBackPID']);
			$content .= '</div>';
			return $content;
		}
		
			// first of all, call the finish method from the payment class
		/// global $GLOBALS['TYPO3_CONF_VARS'];
		// $sysConfig = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extKey]['SYSPRODUCTS']['PAYMENT'];

		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['finishIt']))	{
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['finishIt'] as $classRef)	{
				$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}

			// handle the orders
		$basket = $GLOBALS['TSFE']->fe_user->tx_commerce_basket;
		if ($this->debug)	debug($basket);

			// merge local lang array
		if (is_array($this->LOCAL_LANG) && isset($paymentObj->LOCAL_LANG))	{
			foreach ($this->LOCAL_LANG as $llKey => $llData)	{
				$newLLData = array_merge($llData, (array)$paymentObj->LOCAL_LANG[$llKey]);
				$this->LOCAL_LANG[$llKey] = $newLLData;
			}
		}

		$paymentObj->parentObj = $this;

		if (method_exists($paymentObj, 'hasSpecialFinishingForm') && $paymentObj->hasSpecialFinishingForm($_REQUEST,$this))	{
			$content = $paymentObj->getSpecialFinishingForm($config, $this->MYSESSION, $basket,$this);
			return $content;
		} else {
			if (!$paymentObj->finishingFunction($config, $this->MYSESSION, $basket,$this))	{
				$content .= $this->handlePayment($paymentObj);
				return $content;
			}
		}

		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'postpayment'))	{
				$hookObj->postpayment($paymentObj,$basket,$this);
			}
		}


		/**
		 * Real finishing starts here !
		 */
		
		// save addresses
		// get address types
		$uids = array();
		$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('name', 'tx_commerce_address_types', '1');
		while ($type = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))	{
			$uids[$type['name']] = $this->handleAddress($type['name']);
		}
		$orderData = array();
		$orderData['cust_deliveryaddress'] = ((isset($uids['delivery'])) ? $uids['delivery'] : $uids['billing']);
		$now = time();

		/**
		 * Hook for generating The OrderId
		 */
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'generateOrderId'))	{
				$orderId = $hookObj->generateOrderId($orderId, $basket, $this);
			}
		}

		if (empty($orderId))	{
			$orderId = uniqid('', true);
		}

		$this->orderId=$orderId;

		$orderData['order_id'] = $orderId;
		if (is_array($GLOBALS['TSFE']->fe_user->user))	{
			$orderData['cust_fe_user'] = $GLOBALS['TSFE']->fe_user->user['uid'];
		}
		$orderData['cust_invoice'] = $uids['billing'];
		$orderData['paymenttype'] = $this->getPaymentType(true);
		$orderData['sum_price_net'] = $basket->get_net_sum();
		$orderData['sum_price_gross'] = $basket->get_gross_sum();
		$orderData['order_sys_language_uid'] = $GLOBALS['TSFE']->config['config']['sys_language_uid'];
		/**
		 * Dertermine the Sysfolder, wher to place all datasests
		 * Default (if bo hook us used, the Commerce default folder)
		 */
 		
 		if (isset($this->conf['newOrderPid']) and ($this->conf['newOrderPid'] >0)) {
 			
 			$orderData['pid']= $this->conf['newOrderPid'];
 		}
 		
 		if (empty($orderData['pid']) || ($orderData['pid']< 0)) {
 			
 			$comPid = array_keys(tx_graytree_folder_db::getFolders('commerce', 0, 'COMMERCE'));
			$ordPid = array_keys(tx_graytree_folder_db::getFolders('commerce', $comPid[0], 'Orders'));
			$incPid = array_keys(tx_graytree_folder_db::getFolders('commerce', $ordPid[0], 'Incoming'));
			$orderData['pid'] = $incPid[0];
 		}
		
		$orderData['crdate'] = $now;
		$orderData['tstamp'] = $now;
		/**
		 * @TODO: Change to ISO3 field in static currency to get rid of relation to uid
		 * Those could be changed in new static_currencies Versions in the future
		 */
		$orderData['cu_iso_3_uid'] = $this->conf['currencyId'];
		$orderData['comment'] = $this->piVars['comment'];
		$orderData['pricefromnet'] = $basket->pricefromnet;
		
		// insert order
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'preinsert'))	{
				$hookObj->preinsert($orderData,$this);
			}
		}
		if ($this->debug) debug($orderData);
		$GLOBALS['TYPO3_DB']->exec_INSERTquery('tx_commerce_orders', $orderData);
		$orderUid = $GLOBALS['TYPO3_DB']->sql_insert_id();
			// make orderUid avaible in hookObjects
		$this->orderUid = $orderUid;
			// call the update method from the payment class
 		$paymentObj->updateOrder($orderUid, $this->MYSESSION,$this);

			// save order articles
		if (is_array($basket->basket_items))	{
			foreach ($basket->basket_items as $artUid => $basketItem)	{
				if ($this->debug)	debug($basketItem->article);
				$oaData = array();
				$oaData['pid'] = $orderData['pid'];
				$oaData['crdate'] = $now;
				$oaData['tstamp'] = $now;
				$oaData['article_uid'] = $artUid;
				$oaData['article_type_uid'] = $basketItem->article->get_article_type_uid();
				$oaData['article_number'] = $basketItem->article->get_ordernumber();
				$oaData['title'] = $basketItem->getTitle();
				$oaData['subtitle'] = $basketItem->article->get_subtitle();
				$oaData['price_net'] = $basketItem->get_price_net();
				$oaData['price_gross'] = $basketItem->get_price_gross();
				$oaData['tax'] = $basketItem->get_tax();
				$oaData['amount'] = $basketItem->get_quantity();
				$oaData['order_uid'] = $orderUid;
				$oaData['order_id'] = $orderId;

				if ($this->debug)	debug($oaData);

					// insert
				if ( $this->conf['useStockHandling'] == 1) {
					$basketItem->article->reduceStock($basketItem->get_quantity());
				}
				$GLOBALS['TYPO3_DB']->exec_INSERTquery('tx_commerce_order_articles', $oaData);
			}
		}
		if ( $this->conf['useStockHandling'] == 1) {
			$clearPages = explode(',',$this->conf['clearCacheAfterFinishWithStock']);
			foreach($clearPages as $clearPage) { 
				t3lib_tcemain::clear_cacheCmd($clearPage);
			}
		}

		
		/**
		 * Send the emails
		 */
		$this->userMailOK = $this->sendUserMail($orderId,$orderData);
		$this->adminMailOK = $this->sendAdminMail($orderId,$orderData);
		
		foreach($hookObjectsArr as $hookObj) {
    		if (method_exists($hookObj, 'afterMailSend')) {
        			$markerArray=$hookObj->afterMailSend($orderData,$this);
    		}
		}
		/**
		 * Do the output
		 */
		$content = $this->cObj->getSubpart($this->templateCode, '###FINISH###');
		$markerArray['###LISTING_BASKET###'] = $this->makeBasketView(
			$GLOBALS['TSFE']->fe_user->tx_commerce_basket,
			'###BASKET_VIEW###',
			array(NORMALArticleType)
		);

		$markerArray['###MESSAGE###']='';
		$markerArray['###LISTING_TITLE###'] = $this->pi_getLL('order_confirmation');

		

		  if (method_exists($paymentObj, 'getSuccessData')) {
		       $markerArray['###MESSAGE_PAYMENT_OBJECT###'] = $paymentObj->getSuccessData($this);
		  } else {
		       $markerArray['###MESSAGE_PAYMENT_OBJECT###'] = '';
		  } 

		if ($orderData['cust_deliveryaddress'])	{
			$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tt_address', 'uid='.$orderData['cust_deliveryaddress']);
			if ($data= $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))	{
				$deliveryAdress = $this->makeAdressView($data,'###DELIVERY_ADDRESS###');
			}
		}
		$content = $this->cObj->substituteSubpart($content,'###DELIVERY_ADDRESS###',$deliveryAdress);

		$billingAdress = '';
		if ($orderData['cust_invoice'])	{
			$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tt_address', 'uid='.$orderData['cust_deliveryaddress']);
			if ($data= $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))	{
				$billingAdress = $this->makeAdressView($data,'###BILLING_ADDRESS###');
				$markerArray['###CUST_NAME###']=$data['NAME'];
			}
		}
		$content = $this->cObj->substituteSubpart($content,'###BILLING_ADDRESS###',$deliveryAdress);

		$markerArray = $this->FinishItRenderGoodBadMarker($markerArray);
		
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'ProcessMarker'))	{
				$markerArray=$hookObj->ProcessMarker($markerArray,$this);
			}
		}

		$content = $this->cObj->substituteMarkerArray($this->cObj->substituteMarkerArray($content, $markerArray),$this->languageMarker);

		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'postFinish'))	{
				$hookObj->postFinish($basket,$this);
			}
		}


		// at last remove some things from the session
		// change from mySession true real session key
		if($this->clearSessionAfterCheckout == true) {
			$GLOBALS['TSFE']->fe_user->setKey('ses', tx_commerce_div::generateSessionKey('payment'), NULL);		
			$GLOBALS['TSFE']->fe_user->setKey('ses', tx_commerce_div::generateSessionKey('delivery'), NULL);		
			$GLOBALS['TSFE']->fe_user->setKey('ses', tx_commerce_div::generateSessionKey('billing'), NULL);		
		}
		
		
		$GLOBALS['TSFE']->fe_user->tx_commerce_basket->finishOrder();
		$GLOBALS['TSFE']->fe_user->tx_commerce_basket = t3lib_div::makeInstance('tx_commerce_basket');	
		$GLOBALS['TSFE']->fe_user->tx_commerce_basket->set_session_id($pObj->fe_user->id);
		$GLOBALS['TSFE']->fe_user->tx_commerce_basket->load_data();
		
		return $content;
	}

	

	/** HELPER ROUTINES **/

	/**
	 * Fills the MarkerArray with the correct markers, regarding the success of the order
	 * currently a dummy, will bi filed in future with more error codes
	 * @param	array	 $markerArray
	 * @return	array	$markerArray
	 */

	function FinishItRenderGoodBadMarker($markerArray){
		
		$allOK = true;
		if ($this->finishItOK==true){
			
			$markerArray['###FINISH_MESSAGE_GOOD###'] = $this->pi_getLL('finish_message_good');
			$markerArray['###FINISH_MESSAGE_BAD###'] = '';
		}else{
			$markerArray['###FINISH_MESSAGE_BAD###'] = $this->pi_getLL('finish_message_bad');
			$markerArray['###FINISH_MESSAGE_GOOD###'] = '';
		}
		
		if ($this->userMailOK && $this->adminMailOK) {
			$markerArray['###FINISH_MESSAGE_EMAIL###'] = $this->pi_getLL('finish_message_email');
			$markerArray['###FINISH_MESSAGE_NOEMAIL###'] = '';
		}else{
			$markerArray['###FINISH_MESSAGE_NOEMAIL###'] = $this->pi_getLL('finish_message_noemail');
			$markerArray['###FINISH_MESSAGE_EMAIL###'] = '';
		}
		if ($allOK == true) {
			$markerArray['###FINISH_MESSAGE_THANKYOU###'] = $this->pi_getLL('finish_message_thankyou');
		}else{
			$markerArray['###FINISH_MESSAGE_THANKYOU###'] = '';
		}
		return $markerArray;
	}

	/**
	 * check if all Articles of Basket are in stock
	 * 
	 */
	function checkStock() {
		$return = true;
		if ( $this->conf['useStockHandling'] == 1 AND $this->conf['checkStock'] == 1) {
			$basket = $GLOBALS['TSFE']->fe_user->tx_commerce_basket;			
			if (is_array($basket->basket_items))	{
				foreach ($basket->basket_items as $artUid => $basketItem)	{
					if ($this->debug)	debug($basketItem->article);
					if (!$basketItem->article->hasStock($basketItem->get_quantity())) {
						$basket->change_quantity($artUid, 0);
						$return = false;
					}
				}
			}
			$basket->store_data();
		}			
		return $return;
	} 

	/**
	 * This method returns an general overview about the basket content.
	 * It contains
	 *  - price for all articles (sum net)
	 *  - the price for shipping and package
	 *  - the netto sum
	 *  - the sum for tax
	 *  - the end sum (gross)
	 *
	 * @return	String with basket sum
	 */
	function getBasketSum($type = 'WEB')	{
		$basket = $GLOBALS['TSFE']->fe_user->tx_commerce_basket;
		$sumNet = 0;
		$sumGross = 0;
		$sumTax = 0;
		$sumShipping = 0;

		$template = $this->cObj->getSubpart($this->templateCode, '###LISTING_BASKET_' .strtoupper($type) . '###');

		$sumNet = $basket->get_net_sum();
		$sumGross = $basket->get_gross_sum();

		$sumTax = $sumGross - $sumNet;
		$delivery_article_array=$basket->get_articles_by_article_type_uid_asUidlist(DELIVERYArticleType);
		$sumShippingNet = 0;
		$sumShippingGross = 0;
		foreach ($delivery_article_array as $oneDeliveryArticle)	{
			$sumShippingNet += $basket->basket_items[$oneDeliveryArticle]->get_price_net();
			$sumShippingGross += $basket->basket_items[$oneDeliveryArticle]->get_price_gross();
		}
		$payment_article_array = $basket->get_articles_by_article_type_uid_asUidlist(PAYMENTArticleType);

		$sumPaymentNet = 0;
		$sumPaymentGross = 0;
		foreach ($payment_article_array as $onePaymentArticle)	{
			$sumPaymentNet += $basket->basket_items[$onePaymentArticle]->get_price_net();
			$sumPaymentGross += $basket->basket_items[$onePaymentArticle]->get_price_gross();
		}
		$paymentTitle=$basket->getFirstArticleTypeTitle(PAYMENTArticleType);

		$markerArray = array();
		$markerArray['###LABEL_SUM_ARTICLE_NET###'] = $this->pi_getLL('listing_article_net');
		$markerArray['###LABEL_SUM_ARTICLE_GROSS###'] = $this->pi_getLL('listing_article_gross');
		$markerArray['###SUM_ARTICLE_NET###'] = tx_moneylib::format($sumNet,$this->currency);
		$markerArray['###SUM_ARTICLE_GROSS###'] = tx_moneylib::format($sumGross,$this->currency);
		$markerArray['###LABEL_SUM_SHIPPING_NET###'] = $this->pi_getLL('listing_shipping_net');
		$markerArray['###LABEL_SUM_SHIPPING_GROSS##'] = $this->pi_getLL('listing_shipping_gross');
		$markerArray['###SUM_SHIPPING_NET###'] = tx_moneylib::format($sumShippingNet,$this->currency);
		$markerArray['###SUM_SHIPPING_GROSS###'] = tx_moneylib::format($sumShippingGross,$this->currency);
		$markerArray['###LABEL_SUM_NET###'] = $this->pi_getLL('listing_sum_net');
		$markerArray['###SUM_NET###'] = tx_moneylib::format(($sumNet + $sumShipping),$this->currency);
		$markerArray['###LABEL_SUM_TAX###'] = $this->pi_getLL('listing_tax');
		$markerArray['###SUM_TAX###'] = tx_moneylib::format(intval($sumTax),$this->currency);;
		$markerArray['###LABEL_SUM_GROSS###']= $this->pi_getLL('listing_sum_gross');
		$markerArray['###SUM_GROSS###'] = tx_moneylib::format(intval($sumGross),$this->currency);
		$markerArray['###SUM_PAYMENT_NET###'] = tx_moneylib::format(intval($sumPaymentNet),$this->currency);
		$markerArray['###SUM_PAYMENT_GROSS###'] = tx_moneylib::format(intval($sumPaymentGross),$this->currency);
		$markerArray['###LABEL_SUM_PAYMENT_GROSS###'] = $this->pi_getLL('label_sum_payment_gross');
		$markerArray['###LABEL_SUM_PAYMENT_NET###'] = $this->pi_getLL('label_sum_payment_net');
		$markerArray['###PAYMENT_TITLE###'] = $paymentTitle;

		/**
		 * Hook for processing Marker Array
		 * Inspired by tt_news
		 * @since 21.01.2006
		 *
		 */
		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['getBasketSum']))	{
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['getBasketSum'] as $classRef)	{
				$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'ProcessMarker'))	{
				$markerArray=$hookObj->ProcessMarker($markerArray,$this);
			}
		}

		return $this->cObj->substituteMarkerArray($template, $markerArray);
	}

	/**
	 * Returns a string that contains the address data of the specified type.
	 * The type can be 'billing' or 'delivery'.
	 *
	 * @param	string	$addressType: The type of the address that should be exported from the session
	 * @param	string	$newLine: The string that is used a splitter between the single lines
	 * @return	String with address
	 */
	function getAddress($addressType)	{
		$typeLower = strtolower($addressType);
		$data = $this->parseRawData($this->MYSESSION[$typeLower],$this->conf[$typeLower.'.']['sourceFields.']);
		if (is_array($this->MYSESSION[$typeLower]) && (count($this->MYSESSION[$typeLower]) > 0) && is_array($data)){
			$addressArray = array();
			$addressArray['###HEADER###'] = $this->pi_getLL($addressType.'_title');
			foreach ($data as $key => $value)	{
				$addressArray['###LABEL_'.strtoupper($key).'###'] = $this->pi_getLL('general_' .$key);
				$addressArray['###'.strtoupper($key).'###'] = $value;
			}
			if ($this->conf[$addressType.'.']['subpartMarker.']['listItem']) {
				$template = $this->cObj->getSubpart($this->templateCode, strtoupper($this->conf[$addressType.'.']['subpartMarker.']['listItem']));
			} else {
				$template = $this->cObj->getSubpart($this->templateCode, '###ADDRESS_LIST###');
			}
			return $this->cObj->substituteMarkerArray($template, $addressArray);
		} else {
			return '';
		}
	}

	/**
	 * Checks if an address in the SESSION is valid
	 *
	 */
	function validateAddress($addressType)	{
		$typeLower = strtolower($addressType);
		$config = $this->conf[$typeLower .'.'];
		$returnVal = true;
		if ($this->debug) debug($config, 'TS Config', __LINE__, __FILE__ );
		$this->formError = array();
		
		if ($this->piVars['check'] != $addressType) return true;

		// if the address doesn't exsist in the session it's valid. For the case that
		// not delivery address was set
		$isArray = is_array($this->MYSESSION[$typeLower]);
		
		if (!$isArray && $typeLower == 'delivery') return true;
		if (!$isArray && $typeLower != 'delivery') return false;
		#debug($this->MYSESSION[$typeLower]);
		foreach ($this->MYSESSION[$typeLower] as $name => $value)	{
			if ($config['sourceFields.'][$name .'.']['mandatory'] == 1 && strlen($value) == 0)	{
				$this->formError[$name] = $this->pi_getLL('error_field_mandatory');
				$returnVal = false;
			}
			
			$eval = explode(',', $config['sourceFields.'][$name .'.']['eval']);
			
			foreach ($eval as $method)	{
				$method = explode('_', $method);
				switch (strtolower($method[0]))	{
					case 'email':
						if (!t3lib_div::validEmail($value))	{
							$this->formError[$name] = $this->pi_getLL('error_field_email');
							$returnVal = false;
						}
						break;
					case 'username':
						if($GLOBALS['TSFE']->loginUser){
						break;
						}	
					    
						if (!$this->checkUserName($value))	{
							$this->formError[$name] = $this->pi_getLL('error_field_username');
							$returnVal = false;
						}
						break;
					case 'string':
						if (!is_string($value))	{
							$this->formError[$name] = $this->pi_getLL('error_field_string');
							$returnVal = false;
						}
						break;
					case 'int':
						 if (!is_integer($value) && preg_match('/^\d+$/', $value) !== 1) {
							$this->formError[$name] = $this->pi_getLL('error_field_int');
							$returnVal = false;
						}
						break;
					case 'min':
						if (strlen((string)$value) < intval($method[1]))	{
							$this->formError[$name] = $this->pi_getLL('error_field_min');
							$returnVal = false;
						}
						break;
					case 'max':
						if (strlen((string)$value) > intval($method[1]))	{
							$this->formError[$name] = $this->pi_getLL('error_field_max');
							$returnVal = false;
						}
						break;
					case 'alpha':
						if (preg_match('/[0-9]/', $value) === 1)	{
							$this->formError[$name] = $this->pi_getLL('error_field_alpha');
							$returnVal = false;
						}
						break;
				}
			}
		}

		return $returnVal;
		
	}	
	
	function checkUserName($username){
		
		    $table = 'fe_users';
		    $fields = 'uid';
		    $select = 'username = \''.$username.'\'';
		    $select.= t3lib_befunc::deleteClause($table);
			$select .= ' AND pid = ' . $this->conf['userPID'];
		    $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fields, $table, $select);
		    $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
		    if(is_array($row) && count($row)){
			return false;
		    }
		
		    return true;
	}

	function getPaymentData()	{
		$result = '';
		if (is_array($this->MYSESSION['mails']['payment']))	{
			foreach ($this->MYSESSION['mails']['payment'] as $k => $data)	{
				if ($k <> 'cc_checksum')	{
					$result .= $data['label'] .' : ';
					if ($k == 'cc_number')	{
						$data['data'] = substr($data['data'], 0, -3) .'XXX';
					}
					$result .= $data['data'] ."\n";
				}
			}
		}

		return $result;
	}
	
	
	/**
	 * Returns the payment object and includes the Payment Class. If there is no payment it throws an error
	 *
	 * @return unknown
	 */
	function getPaymentObject()	{
		
		
		$paymentType = $this->getPaymentType();
		$sysConfig = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extKey]['SYSPRODUCTS']['PAYMENT'];
		
		$config = $sysConfig['types'][strtolower((string)$paymentType)];

		$errorStr = NULL;
		if (!isset($config['class']))	{
			$errorStr[] = 'class not set!:'.$config['class'];
		}
		
		if (!file_exists($config['path']))	{
			$errorStr[] = 'file not found!:'.$config['path'];
		}
		
		if (is_array($errorStr))	die ('MAIN:FATAL! No payment possible because I don\'t know how to handle it! ('.implode(', ', $errorStr).')');

		require_once($config['path']);
		$paymentObj = t3lib_div::makeInstance($config['class']);
		if (method_exists($paymentObj, 'setStep'))	{
			$this->piVars['step'] = $paymentObj->setStep($_REQUEST, $this->piVars['step']);
		}
		
		return $paymentObj;
	}
	
	
	/**
	 * Returns the payment type. The type is extracted from the basket object. The type
	 * is stored in the basket as a special article.
	 * @param       boolean $id: switch  for returning the id or classname
	 *
	 * @return	A string that determines the payment type ('creditcard', 'invoice' or whatever
	 *              if not $id is set, otherwise returns the id of the paymentarticle
	 */
	 
	function getPaymentType($id = false)	{
		$basket = $GLOBALS['TSFE']->fe_user->tx_commerce_basket;
		$payment = $basket->get_articles_by_article_type_uid_asuidlist(PAYMENTArticleType);
		if($id){
	                  return $payment[0];
                }					                    
		$paymenttitle = $basket->basket_items[$payment[0]]->article->classname;
		return strtolower($paymenttitle);
	}


	/**
	 * Creates a form from a table where the fields can prefilled, configured
	 * via TypoScript.
	 */
	function getInputForm($config, $step, $parseList = true)	{
			// build a query for selecting an address from the database if we have a logged in user
		if ($parseList)	{
			$fieldList = $this->parseFieldList($config['sourceFields.']);
		} else {
			$fieldList = array_keys($config['sourceFields.']);
		}

	        #$this->dbFieldData = $this->getAddressFromDB($config, $step, $fieldList);
    		 $this->dbFieldData = $this->MYSESSION[$step];

		$fieldTemplate = $this->cObj->getSubpart($this->templateCode, '###SINGLE_INPUT###');
		$fieldTemplateCheckbox = $this->cObj->getSubpart($this->templateCode, '###SINGLE_CHECKBOX###');
		$fieldCode = '';
		foreach ($fieldList as $fieldName)	{
			$fieldMarkerArray = array();
		
			$fieldLabel = $this->pi_getLL($step .'_' .$fieldName, $this->pi_getLL('general_' .$fieldName));

			if ($config['sourceFields.'][$fieldName .'.']['mandatory'] == '1')	{
				$fieldLabel .= ' ' .$this->cObj->stdWrap($config['mandatorySign'],$config['mandatorySignStdWrap.']);
			}

			$fieldMarkerArray['###FIELD_LABEL###'] = $fieldLabel;

				// clear the error field, this has to be implemented in future versions
			if (strlen($this->formError[$fieldName]) > 0)	{
				$fieldMarkerArray['###FIELD_ERROR###'] = $this->cObj->stdWrap($this->formError[$fieldName],$config['fielderror.']);
			} else {
				$fieldMarkerArray['###FIELD_ERROR###'] = '';
			}

				// create input field

			$arrayName = $fieldName .(($parseList) ? '.' : '');
			$fieldMarkerArray['###FIELD_INPUT###'] = $this->getInputField($fieldName, $config['sourceFields.'][$arrayName], $this->MYSESSION[$step][$fieldName],$step);
		    $fieldMarkerArray['###FIELD_NAME###'] = $this->prefixId.'['.$step.'][' .$fieldName .']';
		    $fieldMarkerArray['###FIELD_INPUTID###'] = $step.'-'.$fieldName;
		        
		        
			// save some data for mails
			$this->MYSESSION['mails'][$step][$fieldName] = array('data' => $this->MYSESSION[$step][$fieldName], 'label' => $fieldLabel);
			if($config['sourceFields.'][$arrayName]['type'] == 'check'){
				$fieldCode .= $this->cObj->substituteMarkerArray($fieldTemplateCheckbox, $fieldMarkerArray);
			}else{
				$fieldCode .= $this->cObj->substituteMarkerArray($fieldTemplate, $fieldMarkerArray);
			}
		}
		$GLOBALS['TSFE']->fe_user->setKey('ses',tx_commerce_div::generateSessionKey('mails'), $this->MYSESSION['mails']);
		return $fieldCode;
	}

	function handleAddress($type)	{
		if (!is_array($this->MYSESSION[$type])) return;
		$config = $this->conf[$type .'.'];
		$fieldList = $this->parseFieldList($config['sourceFields.']);
		
		if (is_array($fieldList))	{
			foreach ($fieldList as $fieldName)	{
				$dataArray[$fieldName] = $this->MYSESSION[$type][$fieldName];
			}
		}
		// check if a uid is set, so addresshandling can be used. Only possible if a user is logged in
		if ($this->MYSESSION[$type]['uid']&&$GLOBALS['TSFE']->loginUser)	{
			$uid = $this->MYSESSION[$type]['uid'];
		} else {
			// create
			if (isset($this->conf['addressPid']))	{
				$dataArray['pid'] = $this->conf['addressPid'];
			} else {
				list($commercePid, $defaultFolder, $folderList) = tx_graytree_folder_db::initFolders('Commerce', 'commerce', $modPid);
				$dataArray['pid'] = $commercePid;
			}

			if (isset($GLOBALS['TSFE']->fe_user->user['uid']))	{
				$dataArray[$config['userConnection']] = $GLOBALS['TSFE']->fe_user->user['uid'];
			} else {
					// create a new user if no user is logged in and the option is set
				if ($this->conf['createNewUsers'])	{
					// added some changes for 
					// 1) using email as username by default
					// 2) fill in new fields in table
					// 3) provide data for usermail
					// 4) use billing as default type
					// Volker Graubaum, 01.05.06
					$feuData = array();
					$feuData['pid'] = $this->conf['userPID'];
					$feuData['usergroup'] = $this->conf['userGroup'];
					$feuData['tstamp'] = time();
					if($this->conf['randomUser']){
						$feuData['username'] = substr($this->MYSESSION['billing']['name'], 0, 2) .substr($this->MYSESSION['billing']['surname'], 0, 4) .substr(uniqid(rand()), 0, 4);
					}else{
						$feuData['username'] = $this->MYSESSION['billing']['email'];
					}
					$feuData['password'] = substr(uniqid(rand()), 0, 6);
					$feuData['email'] = $this->MYSESSION['billing']['email'];
					$feuData['name'] = $this->MYSESSION['billing']['name'].' '.$this->MYSESSION['billing']['surname'];
					/**
					 * Hook for processing feUserData
					 * @author Volker Graubaum ( typo3@e-netconsulting.de )
					 * @since 29.12.2007
					 *
					 */
					$hookObjectsArr = array();
					if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['handleAddress']))	{
						foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['handleAddress'] as $classRef)	{
							$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
						}
					}
					foreach($hookObjectsArr as $hookObj)	{
						if (method_exists($hookObj, 'preProcessUserData'))	{
							$hookObj->preProcessUserData($feuData,$this);
						}
					}
					
					$GLOBALS['TYPO3_DB']->exec_INSERTquery('fe_users', $feuData);
					$dataArray[$config['userConnection']] = $GLOBALS['TYPO3_DB']->sql_insert_id();
					$GLOBALS['TSFE']->fe_user->user['uid'] = $dataArray[$config['userConnection']];
					foreach($hookObjectsArr as $hookObj)	{
						if (method_exists($hookObj, 'postProcessUserData'))	{
								$hookObj->postProcessUserData($feuData,$this);
						}
					}
					$this->userData = $feuData;
				}
			}
			$dataArray[$config['sourceLimiter.']['field']] = $config['sourceLimiter.']['value'];
			//first address should be main address by default
			$dataArray['tx_commerce_is_main_address'] = 1;

			$GLOBALS['TYPO3_DB']->exec_INSERTquery(
				'tt_address',
				$dataArray
			);
			$uid = $GLOBALS['TYPO3_DB']->sql_insert_id();	
		}

		return $uid;
	}
	
	function getField($value,$type,$field){
			
		if($this->conf[$type.'.']['sourceFields.'][$field.'.']['table']){
		    $table = $this->conf[$type.'.']['sourceFields.'][$field.'.']['table'];
		    $select = $this->conf[$type.'.']['sourceFields.'][$field.'.']['value'].' = \''.$value.'\'';		    
    		    $fields = $this->conf[$type.'.']['sourceFields.'][$field.'.']['label'];
		    $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fields, $table, $select);
		    $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
		    return $row[$fields];
		}
		
		return $value;

	}

	/**
	 * Returns a single input form field.
	 */
	function getInputField($fieldName, $fieldConfig,$fieldValue, $step)	{
		if ($this->debug) debug($step);
		if ($this->debug) debug($fieldConfig);
		if ($this->debug) debug($fieldValue);
		switch (strtolower($fieldConfig['type']))	{
			case 'select':
				return $this->getSelectInputField($fieldName, $fieldConfig,  $fieldValue ,$step);
			case 'static_info_tables':
				$selected = $fieldValue != '' ? $fieldValue : $fieldConfig['default'];
			 	return $this->staticInfo->buildStaticInfoSelector($fieldConfig['field'], $this->prefixId.'[' .$step .'][' .$fieldName .']', $fieldConfig['cssClass'],$selected,'','',$step.'-'.$fieldName,'',$fieldConfig['select']);
                        case 'check':
			            return $this->getCheckboxInputField($fieldName, $fieldConfig,  $fieldValue,$step);
			case 'single':
			default:
				return $this->getSingleInputField($fieldName, $fieldConfig,$step);
		}
	}

	/**
	 * Returns a single textfield
	 */
	function getSingleInputField($fieldName, $fieldConfig, $step)	{

		if (($fieldConfig['default']) && empty($this->dbFieldData[$fieldName]))	{
			$value = $fieldConfig['default'];
		} else {
			$value = $this->dbFieldData[$fieldName];
		}
		
		$maxlength = '';
		if(isset($fieldConfig['maxlength']) AND is_numeric($fieldConfig['maxlength'])) {
			$maxlength = ' maxlength="'.$fieldConfig['maxlength'].'"' ;
		}
		
		$result = '<input id="'.$step.'-'.$fieldName.'" type="text" name="'.$this->prefixId.'['.$step.'][' .$fieldName .']" value="' .$value .'" ' . $maxlength;
		if ($fieldConfig['readonly'] == 1)	{
			$result .= ' readonly disabled /><input type="hidden" name="'.$this->prefixId.'['.$step.'][' .$fieldName .']" value="' .$value .'" ' . $maxlength;' />';
		}else{
			$result .= '/>';
		}

		return $result;
	}

	/**
	 * Returns a selectbox
	 */

        function getSelectInputField($fieldName, $fieldConfig, $fieldValue = '',$step = '') {

                $result = '<select id="'.$step.'-'.$fieldName.'" name="'.$this->prefixId.'['.$step.'][' .$fieldName .']">';
                if ($fieldValue != '')  {
                            $fieldConfig['default'] = $fieldValue;
                }
                 // if static items are set
	                 if (is_array($fieldConfig['values'])) {
	                         foreach ($fieldConfig['values'] as $option) {
	                                 $result .= '<option name="' .$option .'" value="' .$option .'"';
	                                 if ($fieldValue === $option)    $result .= ' selected="selected"';
		                             $result .= '>' .$option .'</option>' ."\n";
			         }
			}else {
	                        // try to fetch some data from database
	                        $table = $fieldConfig['table'];
	                        $select = $fieldConfig['select'] .$this->cObj->enableFields($fieldConfig['table']);
	                        $fields = $fieldConfig['label'] .' AS label,' .$fieldConfig['value'] .' AS value';
				$orderby = ($fieldConfig['orderby']) ? $fieldConfig['orderby'] : '';
		                $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fields, $table, $select, '',$orderby);
		                while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
				#name="' .$row['value'] .'"
		                        $result .= '<option  value="' .$row['value'] .'"';
		                        if ($row['value'] === $fieldConfig['default'])  $result .= ' selected="selected"';
			                $result .= '>' .$row['label'] .'</option>' ."\n";
			        }
			}
    			$result .= '</select>';
                        return $result;
	}			

        /**
         * Returns a checkbox
         *
         * @param       string          $fieldname: The name of the field
         * @param       array           $fieldConf: The configuration for this field (normally from TypoScript)
         * @param       string          $fieldValue: The current value of this field (Normally fetched from piVars)
         * @param       string          $step: name of the step
         * @return      a single checkbox
         */

        function getCheckboxInputField($fieldName, $fieldConfig, $fieldValue = '',$step = '') {
            $result = '<input id="'.$step.'-'.$fieldName.'" type="checkbox" name="'.$this->prefixId.'['.$step.']['.$fieldName.']"
            id="'.$this->prefixId.'['.$step.']['.$fieldName.']" value="1" ';
            if (($fieldConfig['default']=='1' && $fieldValue!=0) || $fieldValue==1) {
                $result.='checked="checked" ';
            }
            $result .= ' /> ';
            if ($fieldConfig['additionalinfo']!='') {
                  $result.=$fieldConfig['additionalinfo'];
            }
              return $result;
        }



	/**
	 * Creates a list of array keys where the last character is removed from it
	 * but only if the last character is a dot (.)
	 *
	 */
	function parseFieldList($fieldConfig)	{
		$result = array();
		if (!is_array($fieldConfig)) return $result;

		foreach ($fieldConfig as $key => $data)	{
				// remove the trailing '.'
			if (substr($key,-1) == '.') {
				$result[] = substr($key, 0, -1);
			} else {
				$result[] = $key;
			}
		}

		return $result;
	}

	/**
	 * Returns wether a checkout is allowed or not.
	 * It can return different types of results. Possible keywords are:
	 *	- noarticles	=> User has not articles in basket
	 *	- nopayment		=> User has no payment type selected
	 *	- nobilling		=> User is in step 'finish' but no billing address was set
	 *
	 * @return	TRUE if checkout is possible, otherwise it returns on of keywords listed above
	 */
	function canMakeCheckout()	{

		$checks = array('noarticles','nopayment','nobilling');
		$myCheck = false;

		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['canMakeCheckout']))	{
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['canMakeCheckout'] as $classRef)	{
				$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}
		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'canMakeCheckoutOwnTests'))	{
				$hookObj->canMakeCheckoutOwnTests($checks,$myCheck);
			}
		}
		
		// check if the hooks returns an error
		if (strlen($myCheck) >= 1)	{
			return $myCheck;
		}

		// check if the basket is empty
		if (in_array('noarticles',$checks) && !$GLOBALS['TSFE']->fe_user->tx_commerce_basket->hasArticles(NORMALArticleType))	{
			return 'noarticles';
		}

		// check if we a payment article in the basket
		if(in_array('nopayment',$checks)) {

			$paymentArticles = $GLOBALS['TSFE']->fe_user->tx_commerce_basket->get_articles_by_article_type_uid_asUidlist(PAYMENTArticleType);
			if (count($paymentArticles) <= 0)	{
				return 'nopayment';
			}
		}

		// check if we have a delivery address, some payment infos and if we are in the finishing step
		if (in_array('nobilling',$checks) && $this->currentStep == 'finish' && !isset($this->MYSESSION['billing']))	{
			return 'nobilling';
		}

		// if we reach this point, everything is fine and we can return a positive result
		return true;
	}

	/**
	 * Sends the Information Mail to the user
	 * @since 12th November 2005
	 * Also performes a charset Conversion for the mail
	 * @param Order ID
	 * @param Order Data
	 * @retunr returns true if success
	 */
	function sendUserMail($orderUid, $orderData)	{

		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['sendUserMail']))	{
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['sendUserMail'] as $classRef)	{
				$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}

		if (strlen($this->MYSESSION['billing']['email'])) {
			/**
			 * if use has email in the formular, use this
			 */
			$userMail = $this->MYSESSION['billing']['email'];
		}
		elseif (is_array($GLOBALS['TSFE']->fe_user->user) && strlen($GLOBALS['TSFE']->fe_user->user['email']))	{
			$userMail = $GLOBALS['TSFE']->fe_user->user['email'];
		} else{
			return false;
		}


		$userMail = tx_commerce_div::validEmailList($userMail);
		
		if ($userMail && !eregi("\r",$userMail) && !eregi("\n",$userMail))	{

			foreach($hookObjectsArr as $hookObj)	{
				if (method_exists($hookObj, 'getUserMail'))	{
					$hookObj->getUserMail($userMail,$orderUid,$orderData);
				}
			}
			if ($userMail != '' && $this->cObj->checkEmail($userMail))	{
				$UserMailObj=t3lib_div::makeInstance('tx_commerce_pi3');
				$UserMailObj->conf = $this->conf;
				$UserMailObj->pi_setPiVarDefaults();
				$UserMailObj->cObj=$this->cObj;
				$UserMailObj->pi_loadLL();
				$UserMailObj->staticInfo = &$this->staticInfo;
				$UserMailObj->currency = $this->currency;
				$UserMailObj->showCurrency = $this->conf['usermail.']['showCurrency'];
				$UserMailObj->templateCode=$this->cObj->fileResource($this->conf['usermail.']['templateFile']);
				$UserMailObj->generateLanguageMarker();
				$UserMailObj->userData = $this->userData;
				foreach($hookObjectsArr as $hookObj)	{
					if (method_exists($hookObj, 'preGenerateMail'))	{
						$hookObj->preGenerateMail($UserMailObj,$this);
					}
				}

				$mailcontent=$UserMailObj->generateMail($orderUid, $orderData,$userMarker);

				foreach($hookObjectsArr as $hookObj)	{
					if (method_exists($hookObj, 'PostGenerateMail'))	{
						$hookObj->PostGenerateMail($UserMailObj,$this,$GLOBALS['TSFE']->fe_user->tx_commerce_basket,$mailcontent);
					}
				}
				if($this->conf['usermail.']['useHtml'] == '1' && $this->conf['usermail.']['templateFileHtml']) {
					$UserMailObj->templateCode=$this->cObj->fileResource($this->conf['usermail.']['templateFileHtml']);
					$htmlContent=$UserMailObj->generateMail($orderUid, $orderData,$userMarker,true);
	
					foreach($hookObjectsArr as $hookObj)	{
						if (method_exists($hookObj, 'PostGenerateMail'))	{
							$hookObj->PostGenerateMail($UserMailObj,$this,$GLOBALS['TSFE']->fe_user->tx_commerce_basket,$htmlContent);
						}
					}
				}
				/**
				 * @since 2005 12th November
				 * Noved to plainMailEncoded
				 */
				$parts = split(chr(10),$mailcontent,2);		// First line is subject
				$subject=trim($parts[0]);
				$plain_message=trim($parts[1]);

				
				/**
				 * Check if charset ist set by TS
				 * Otherwise set to default Charset
				 * Checck if mailencoding ist set
				 * otherwise set to 8bit
				 */
				if (!$this->conf['usermail.']['charset'])	{
					$this->conf['usermail.']['charset']=$GLOBALS['TSFE']->renderCharset;
				}
				if (!$this->conf['usermail.']['encoding'])	{
				 	$this->conf['usermail.']['encoding']='8bit';
				}

				/**
				 * Convert Text to charset
				 */
				$GLOBALS['TSFE']->csConvObj->initCharset($GLOBALS['TSFE']->renderCharset);
				$GLOBALS['TSFE']->csConvObj->initCharset(strtolower($this->conf['usermail.']['charset']));
				$plain_message=$GLOBALS['TSFE']->csConvObj->conv($plain_message,$GLOBALS['TSFE']->renderCharset,strtolower($this->conf['usermail.']['charset']));
				$subject=$GLOBALS['TSFE']->csConvObj->conv($subject,$GLOBALS['TSFE']->renderCharset,strtolower($this->conf['usermail.']['charset']));

				if ($this->debug)	print "<b>Usermail to $userMail</b><pre>$plain_message</pre>\n";
				
				/**
				* Mailconf for  tx_commerce_div::sendMail($mailconf);
				*
				* @author	Tom Rüther <tr@e-netconsulting.de>
				* @since	29th June 2008
				**/
				$mailconf = array(
					'plain' => Array (
								'content'=> $plain_message
								),
					'html' => Array (
						'content'=> $htmlContent,
						'path' => '',
						'useHtml' => $this->conf['usermail.']['useHtml']
					),
					'defaultCharset' => $this->conf['usermail.']['charset'],
					'encoding' => $this->conf['usermail.']['encoding'],
					'attach' => $this->conf['usermail.']['attach.'],
					'alternateSubject' => $this->conf['usermail.']['alternateSubject'],
					'recipient' => $userMail.','.$this->conf['usermail.']['cc'], 
					'recipient_copy' =>  $this->conf['usermail.']['bcc'],
					'fromEmail' => $this->conf['usermail.']['from'], 
					'fromName' => $this->conf['usermail.']['from_name'],
					'replayTo' => $this->conf['usermail.']['from'], 
					'priority' => $this->conf['usermail.']['priority'], 
					'callLocation' => 'sendUserMail' 
				);

				tx_commerce_div::sendMail($mailconf);
				return true;
			}
		}

		return false;
	}

	/**
	 * Sends Admin Mail
	 * @since 12th November 2005
	 * Also performes a charset Conversion for the mail, including Sender
	 * @param Order ID
	 * @param Order Data
	 * @retunr returns true if success
	 */
	function sendAdminMail($orderUid, $orderData)	{
		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['sendAdminMail']))	{
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['sendAdminMail'] as $classRef)	{
				$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}

		if (is_array($GLOBALS['TSFE']->fe_user->user&&strlen($GLOBALS['TSFE']->fe_user->user['email'])))	{
			$userMail = $GLOBALS['TSFE']->fe_user->user['email'];
		} else {
		 	$userMail = $this->MYSESSION['billing']['email'];
		}

		if (is_array($GLOBALS['TSFE']->fe_user->user&&strlen($GLOBALS['TSFE']->fe_user->user['email'])))	{
			$userName = $GLOBALS['TSFE']->fe_user->user['name'].' '.$GLOBALS['TSFE']->fe_user->user['surname'];
		} else {
		 	$userName = $this->MYSESSION['billing']['name'].' '.$this->MYSESSION['billing']['surname'];
		}

		if ($this->conf['adminmail.']['from'] || $userMail)	{
			$AdminMailObj=t3lib_div::makeInstance('tx_commerce_pi3');
			$AdminMailObj->conf = $this->conf;
			$AdminMailObj->pi_setPiVarDefaults();
			$AdminMailObj->cObj=$this->cObj;
			$AdminMailObj->pi_loadLL();
		
			$AdminMailObj->staticInfo = &$this->staticInfo;
			
			$AdminMailObj->currency = $this->currency;
			$AdminMailObj->showCurrency = $this->conf['adminmail.']['showCurrency'];
			$AdminMailObj->templateCode=$this->cObj->fileResource($this->conf['adminmail.']['templateFile']);
			$AdminMailObj->generateLanguageMarker();
			$AdminMailObj->userData = $this->userData;
			
			foreach($hookObjectsArr as $hookObj)	{
				if (method_exists($hookObj, 'preGenerateMail'))	{
					$hookObj->preGenerateMail($AdminMailObj,$this);
				}
			}
						
			$mailcontent=$AdminMailObj->generateMail($orderUid, $orderData);
			
			foreach($hookObjectsArr as $hookObj)	{
			    if (method_exists($hookObj, 'PostGenerateMail'))	{
			    	$hookObj->PostGenerateMail($AdminMailObj,$this,$GLOBALS['TSFE']->fe_user->tx_commerce_basket,$mailcontent,$this);
			    }
			}
			
			if($this->conf['adminmail.']['useHtml'] == '1' && $this->conf['adminmail.']['templateFileHtml']) {
				$AdminMailObj->templateCode=$this->cObj->fileResource($this->conf['adminmail.']['templateFileHtml']);
				$htmlContent=$AdminMailObj->generateMail($orderUid, $orderData,'',true);
	
				foreach($hookObjectsArr as $hookObj)	{
					if (method_exists($hookObj, 'PostGenerateMail'))	{
						$hookObj->PostGenerateMail($AdminMailObj,$this,$GLOBALS['TSFE']->fe_user->tx_commerce_basket,$htmlContent);
					}
				}
			}
			/**
			 * @since 2005 12th November
			 * Noved to plainMailEncoded
			 */
			$parts = split(chr(10),$mailcontent,2);		// First line is subject
			$subject=trim($parts[0]);
			$plain_message=trim($parts[1]);

			/**
			 * Check if charset ist set by TS
			 * Otherwise set to default Charset
			 * Checck if mailencoding ist set
			 * otherwise set to 8bit
			 */
			if (!$this->conf['adminmail.']['charset'])	{
				$this->conf['adminmail.']['charset']=$GLOBALS['TSFE']->renderCharset;
			}
			if (!$this->conf['adminmail.']['encoding '])	{
			 	$this->conf['adminmail.']['encoding ']='8bit';
			}

			/**
			 * Convert Text to charset
			 */
			$GLOBALS['TSFE']->csConvObj->initCharset($GLOBALS['TSFE']->renderCharset);
			$GLOBALS['TSFE']->csConvObj->initCharset(strtolower($this->conf['adminmail.']['charset']));
			$plain_message=$GLOBALS['TSFE']->csConvObj->conv($plain_message,$GLOBALS['TSFE']->renderCharset,strtolower($this->conf['adminmail.']['charset']));
			$subject=$GLOBALS['TSFE']->csConvObj->conv($subject,$GLOBALS['TSFE']->renderCharset,strtolower($this->conf['adminmail.']['charset']));
			$username_mailencoded=$GLOBALS['TSFE']->csConvObj->specCharsToASCII($GLOBALS['TSFE']->renderCharset,$userName);

			/**
			 * Check if user Mail is set
			 */
			if (($userMail) && ($userName))	{
				$mailconf['fromEmail'] = $username_mailencoded;
				$mailconf['fromName'] = $userMail;
			} else	{
				$mailconf['fromEmail'] = $this->conf['adminmail.']['from_name'];
				$mailconf['fromName'] = $this->conf['adminmail.'];
			}

			if ($this->debug)	print "<b>Adminmail from </b><pre>$plain_message</pre>\n";
		
			/**
			* Mailconf for  tx_commerce_div::sendMail($mailconf);
			*
			* @author	Tom R√ºther <tr@e-netconsulting.de>
			* @since	29th June 2008
			**/
			$mailconf = array(
				'plain' => Array (
							'content'=> $plain_message
							),
				'html' => Array (
					'content'=> $htmlContent,
					'path' => '',
					'useHtml' => $this->conf['adminmail.']['useHtml']
				),
				'defaultCharset' => $this->conf['adminmail.']['charset'],
				'encoding' => $this->conf['adminmail.']['encoding'],
				'attach' => $this->conf['adminmail.']['attach.'],
				'alternateSubject' => $this->conf['adminmail.']['alternateSubject'],
				'recipient' => $this->conf['adminmail.']['mailto'].','.$this->conf['usermail.']['cc'], 
				'recipient_copy' =>  $this->conf['adminmail.']['bcc'],
				'replayTo' => $this->conf['adminmail.']['from'], 
				'priority' => $this->conf['adminmail.']['priority'], 
				'callLocation' => 'sendAdminMail' 
			);
		
			tx_commerce_div::sendMail($mailconf);
				return true;
		}

		return false;
	}

	/**
	 * Generates one Mail
	 * @param 	string	$orderUid	The Order UID
	 * @param	array	$orderData	Collected Order Data form PI3
	 * @return MailContent
	 */
	function generateMail($orderUid, $orderData,$userMarker = array())	{
		$content='';
		$markerArray=$userMarker;
		$markerArray['###ORDERID###']=$orderUid;
		$markerArray['###ORDERDATE###']=date($this->conf['generalMail.']['orderDate_format'],$orderData['tstamp']);
		$markerArray['###COMMENT###']=$orderData['comment'];
		
		$markerArray['###LABEL_PAYMENTTYPE###']= $this->pi_getLL('payment_paymenttype_' .$orderData['paymenttype'],$orderData['paymenttype']);
		
		/**
		 * Since The first line of the mail is the Suibject, trim the template
		 */

		$template = ltrim($this->cObj->getSubpart($this->templateCode, '###MAILCONTENT###'));
		/*
		 *added replacing marker for New Users
		 *@author Volker Graubaum
		 *@since 01.05.06
		 */
		
		$templateUser = ''; 
		if(is_array($this->userData)){
			$templateUser = trim($this->cObj->getSubpart($template, '###NEW_USER###'));
			$templateUser = $this->cObj->substituteMarkerArray($templateUser,$this->userData,'###|###',1);
		}
		$content = $this->cObj->substituteSubpart($template,'###NEW_USER###',$templateUser);

		$basketContent = $this->makeBasketView(
			$GLOBALS['TSFE']->fe_user->tx_commerce_basket,
			'###BASKET_VIEW###',
			t3lib_div::intExplode(',', $this->conf['regularArticleTypes'])
		);

		$content = $this->cObj->substituteSubpart($content,'###BASKET_VIEW###',$basketContent);

		// Get The addresses
		$deliveryAdress='';
		if ($orderData['cust_deliveryaddress'])	{
			$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tt_address', 'uid='.$orderData['cust_deliveryaddress']);
			if ($data= $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))	{
			    $data = $this->parseRawData($data,$this->conf['delivery.']['sourceFields.']);	
			    $deliveryAdress = $this->makeAdressView($data,'###DELIVERY_ADDRESS###');
			}
		}

		$content = $this->cObj->substituteSubpart($content,'###DELIVERY_ADDRESS###',$deliveryAdress);
		$billingAdress = '';
		if ($orderData['cust_invoice'])	{
			$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tt_address', 'uid='.$orderData['cust_invoice']);
			if ($data= $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))	{
				$data = $this->parseRawData($data,$this->conf['billing.']['sourceFields.']);
				$billingAdress = $this->makeAdressView($data,'###BILLING_ADDRESS###');
				$markerArray['###CUST_NAME###']=$data['NAME'];
			}
		}
		$content = $this->cObj->substituteSubpart($content,'###BILLING_ADDRESS###',$billingAdress);
		
		/**
		 * Hook for processing Marker Array
		 * Inspired by tt_news
		 * @since 21.01.2006
		 *
		 */
		$hookObjectsArr = array();
		if (is_array ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['generateMail']))	{
			foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['commerce/pi3/class.tx_commerce_pi3.php']['generateMail'] as $classRef)	{
				$hookObjectsArr[] = &t3lib_div::getUserObj($classRef);
			}
		}

		foreach($hookObjectsArr as $hookObj)	{
			if (method_exists($hookObj, 'ProcessMarker'))	{
				$markerArray=$hookObj->ProcessMarker($markerArray,$this);
			}
		}
		
		
		$markerArray = array_merge((array)$markerArray,(array)$additionalMarker);
		$markerArray = array_merge((array)$markerArray,(array)$this->languageMarker);
		$content = $this->cObj->substituteMarkerArray($content, $markerArray);

		return ltrim($content);
	}

	/**
	 * parses raw data array from db and replace keys with matching values (select
	 * fields) like country in address data
	 * @param $data array address data
	 * @param $TS array TypoScript for addresshandling for this type
	 * @return $data array address data
	 */
	function parseRawData ($data=array(),$TS) {
		if (!is_array($data))	return array();
		if ($this->debug) debug($TS);
		foreach ($data as $key => $value) {
			$upperKey = strtoupper($key);
			// get the value from the database if the field is a select box
			if ($TS[$key .'.']['type'] == 'select')	{
				$fieldConfig = $TS[$key .'.'];
				$table = $fieldConfig['table'];
				$select = $fieldConfig['value'] .'=\'' .$value .'\'' .$this->cObj->enableFields($fieldConfig['table']);
				$fields = $fieldConfig['label'] .' AS label,';
				$fields.= $fieldConfig['value'] .' AS value';
				$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fields, $table, $select);
				$value = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
				$data[$key] = $value['label'];
			}
			if($TS[$key .'.']['type'] == 'static_info_tables'){
				$fieldConfig = $TS[$key .'.'];
				$field = $fieldConfig['field'];
				$valueHidden = $this->staticInfo->getStaticInfoName($field, $value);
				$value = $valueHidden;
				$data[$key] = $valueHidden;
			}
		}
		return $data;
	}



}

if (defined('TYPO3_MODE') && $GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']["ext/commerce/pi3/class.tx_commerce_pi3.php"])	{
	include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']["ext/commerce/pi3/class.tx_commerce_pi3.php"]);
}
